﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unity.Errors.types;

namespace Unity.Logic.Expressions.statements
{
    public delegate TConclusion DConclusionEvaluateHandler<TTComponent>(
        GComponent<TTComponent> self
       , EStatementType stmt
       , GComponent<TTComponent> other);

    public class GStatement<TTComponent> : TStatementBase, ILogic
    {
        #region ctors
        public GStatement(GComponent<TTComponent> cSelf
            , EStatementType statementOperator
            , GComponent<TTComponent> cOther)
            : base(statementOperator)
        {
            _ComponentSelf = cSelf;
            _ComponentOther = cOther;
        }
        #endregion

        #region properties
        private GComponent<TTComponent> _ComponentSelf;
        private GComponent<TTComponent> _ComponentOther;
        public DConclusionEvaluateHandler<TTComponent> ConclusionEvaluater;
        #endregion

        #region ILogic Members
        public TConclusion Conclusion
        {
            get
            {
                SErrorManager.CustomError()
                .Assert(ConclusionEvaluater != null
                    , new TErrorInfo(GetType(), "Conclusion.get")
                    , "Conclusion handler not initialized. Add a method.");
                return ConclusionEvaluater(_ComponentSelf, StatementType, _ComponentOther);
            }
        }
        public ILogic EvaluateConclusionWith(ILogic logic, ERelationType relation)
        {
            switch (relation)
            {
                case ERelationType.NOT:
                    logic.Conclusion.Result = !logic.Conclusion.Result;
                    return logic;
                    break;
                case ERelationType.AND:
                    logic.Conclusion.Result = this.Conclusion.Result && logic.Conclusion.Result;
                    return logic;
                    break;
                case ERelationType.OR:
                    logic.Conclusion.Result = this.Conclusion.Result || logic.Conclusion.Result;
                    return logic;
                    break;
                case ERelationType.EQV:
                    logic.Conclusion.Result = this.Conclusion.Result == logic.Conclusion.Result;
                    return logic;
                    break;
                case ERelationType.NEQV:
                    logic.Conclusion.Result = this.Conclusion.Result != logic.Conclusion.Result;
                    return logic;
                    break;
                case ERelationType.NA:
                    SErrorManager.Exception()
                        .Throw(new InvalidOperationException()
                        , new TErrorInfo(GetType(), "EvaluateConclusionWith")
                        , "ERelationType can not be NA. It must be assigned.");
                    break;
            }
            return logic;
        }
        public string Text
        {
            get
            {
                return String.Format("({0} {1} {2})"
                    , _ComponentSelf.Alias
                    , StatementMark
                    , _ComponentOther.Value.ToString());
            }
        }
        #endregion
    }
}
